package cn.iot.sys.service.impl;


import cn.iot.common.utils.BaiduAIUtils;
import cn.iot.common.utils.JwtTokenUtil;
import cn.iot.common.utils.RedisUtils;
import cn.iot.common.utils.SysUserUtils;
import cn.iot.common.annotation.DataScope;
import cn.iot.common.constant.CommonConstant;
import cn.iot.sys.dao.SysUserDao;
import cn.iot.sys.entity.SysUser;
import cn.iot.sys.service.SysUserRoleService;
import cn.iot.sys.service.SysUserService;
import cn.hutool.core.util.StrUtil;
import cn.iot.sys.vo.LoginInfoVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 后台用户表
 */
@Slf4j
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserService {

    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysUserDao sysUserDao;

    @Autowired
    private RedisUtils redisUtils;


    @Override
    public SysUser getByUserName(String username) {
        QueryWrapper<SysUser> qe = new QueryWrapper<SysUser>().eq("username", username);
        return this.baseMapper.selectOne(qe);
    }

    @Override
    public String login(String username, String password, HttpServletRequest request) {
        String token = null;
        //密码需要客户端加密后传递
        try {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (!passwordEncoder.matches(password, userDetails.getPassword()) &&  !userDetails.getPassword().equals(password)) {
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails.getUsername());

            SysUser sysUser = SysUserUtils.getSysUser();
            // 保存在线信息 TODO


            boolean singleLogin = false;

            if (singleLogin) {
                //踢掉之前已经登录的token TODO

            }
        } catch (AuthenticationException e) {
            log.warn("登录异常:{}", e.getMessage());
        }
        return token;
    }

    @Override
    public String refreshToken(String oldToken) {
        String token = oldToken.substring(jwtTokenUtil.getTokenHead().length());
        if (jwtTokenUtil.canRefresh(token)) {
            return jwtTokenUtil.refreshToken(token);
        }
        return null;
    }

    @Override
    public SysUser getUserById(Long id) {
        return getById(id);
    }


    @Override
    public int update(Long id, SysUser user) {
        user.setId(id);
        return this.baseMapper.updateById(user);
    }

    @Override
    public int delete(Long id) {
        return this.baseMapper.deleteById(id);
    }

    @Override
    @DataScope(userId = "id")
    public IPage<SysUser> getPage(Map<String, Object> params) {
        int pageSize = Integer.parseInt(String.valueOf(params.get("pageSize")));
        int pageNum = Integer.parseInt(String.valueOf(params.get("pageNum")));

        String username = (String) params.get("username");
        String phone = (String) params.get("phone");
        String deptId = (String) params.get("deptId");
        String beginTime = (String) params.get("beginTime");
        String endTime = (String) params.get("endTime");
        String status = (String) params.get("status");

        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(username)) {
            wrapper.like(SysUser::getUsername, username);
        }
        if (StrUtil.isNotEmpty(phone)) {
            wrapper.like(SysUser::getPhone, phone);
        }
        if (StrUtil.isNotEmpty(deptId)) {
            wrapper.apply("(dept_id = " + deptId + " OR dept_id IN ( SELECT t.id FROM sys_dept t WHERE FIND_IN_SET ( " + deptId + " , ancestors ) ))");
        }
        if (StrUtil.isNotEmpty(beginTime)) {
            wrapper.gt(SysUser::getCreateTime, beginTime);
        }

        if (StrUtil.isNotEmpty(endTime)) {
            wrapper.lt(SysUser::getCreateTime, endTime);
        }
        if (StrUtil.isNotEmpty(status)) {
            wrapper.eq(SysUser::getStatus, status);
        }
        wrapper.apply(params.get(CommonConstant.SQL_FILTER) != null, (String) params.get(CommonConstant.SQL_FILTER));
        return page(new Page<>(pageNum, pageSize), wrapper);
    }

    @Override
    public int updateUserAndRole(SysUser user) {
        //先删除用户与角色关系
        sysUserRoleService.delAndCreateRole(user.getId(), user.getRoleIds());
        // 更新用户
        return this.baseMapper.updateById(user);
    }

    @Override
    public int updatePasswordByUserId(Long userId, String newPassword) {
        SysUser user = new SysUser();
        user.setPassword(newPassword);
        user.setId(userId);
        return this.baseMapper.updateById(user);
    }

    @Override
    public int updateStatus(Long id, String status) {
        SysUser user = new SysUser();
        user.setId(id);
        user.setStatus(status);
        return this.baseMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUserAndRole(SysUser user) {
        int result = this.baseMapper.insert(user);
        //保存用户与角色关系
        sysUserRoleService.insertUserAndUserRole(user.getId(), user.getRoleIds());
        return result;
    }

    @Override
    public int deleteByIds(Long[] ids) {
        return this.baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    @Override
    public List<SysUser> getExportList(Map<String, Object> params) {

        String username = (String) params.get("username");
        String phone = (String) params.get("phone");
        String deptId = (String) params.get("deptId");
        String beginTime = (String) params.get("beginTime");
        String endTime = (String) params.get("endTime");
        String status = (String) params.get("status");

        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(username)) {
            wrapper.like(SysUser::getUsername, username);
        }
        if (StrUtil.isNotEmpty(phone)) {
            wrapper.like(SysUser::getPhone, phone);
        }
        if (StrUtil.isNotEmpty(deptId)) {
            wrapper.apply("(dept_id = " + deptId + " OR dept_id IN ( SELECT t.id FROM sys_dept t WHERE FIND_IN_SET ( " + deptId + " , ancestors ) ))");
        }
        if (StrUtil.isNotEmpty(beginTime)) {
            wrapper.gt(SysUser::getCreateTime, beginTime);
        }

        if (StrUtil.isNotEmpty(endTime)) {
            wrapper.lt(SysUser::getCreateTime, endTime);
        }
        if (StrUtil.isNotEmpty(status)) {
            wrapper.eq(SysUser::getStatus, status);
        }
        wrapper.apply(params.get(CommonConstant.SQL_FILTER) != null, (String) params.get(CommonConstant.SQL_FILTER));
        return list(wrapper);
    }

    @Override
    public List<SysUser> getListAll() {
        return list(new LambdaQueryWrapper<SysUser>());
    }

    @Override
    public List<SysUser> getClassTeacherList() {
        return sysUserDao.getClassTeacherList();
    }

    @Override
    public List<SysUser> getDorTeacherList() {
        return sysUserDao.getDorTeacherList();
    }

    @Override
    public String getLoginRoleNames(String username) {
        LoginInfoVo loginInfoVo=sysUserDao.getLoginInfo(username);
        return loginInfoVo.getRoleName();
    }

    @Override
    public List<SysUser> getRoleUserList(Long roleId) {
        return sysUserDao.getRoleUserList(roleId);
    }

    @Override
    public Map<String, Object> autoFaceLogin(String imageBase64,HttpServletRequest request) {
//        String baiduToken = redisUtils.get("baidu_face_token");
        String baiduToken = "";
        String accessToken = "";
        if(StringUtils.isEmpty(baiduToken)){
            accessToken = BaiduAIUtils.getAuth();
            redisUtils.set("baidu_face_token",accessToken,2592000);
        }
        String resultStr = BaiduAIUtils.getFaceDiffInfo(accessToken,imageBase64);
        log.info(resultStr);
        JSONObject json = JSON.parseObject(resultStr);
        boolean isSuccess = false;
        String baiduUserId = null;
        Map<String,Object> resultMap = new HashMap<>();
        if("0".equals(String.valueOf(json.get("error_code")))){//识别成功
            String result = JSON.toJSONString(json.get("result"));
            String userListStr = JSON.toJSONString(JSON.parseObject(result).get("user_list"));
            List<Map<String,Object>> userList = JSON.parseObject(userListStr,List.class);
            for(Map<String,Object> map:userList){
                baiduUserId = (String)map.get("user_id");
                BigDecimal score = new BigDecimal(String.valueOf(map.get("score")));
                BigDecimal threshold = new BigDecimal("95");
                if(score.compareTo(threshold)>=0){
                    //识别成功
                    isSuccess = true;
                    break;
                }
            }
            //系统用户ID
            String sysUserId = baiduUserId.split("_")[1];
            LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysUser::getId,sysUserId);
            SysUser sysuser = sysUserDao.selectOne(wrapper);
            String token = this.login(sysuser.getUsername(),sysuser.getPassword(),request);
            resultMap.put("token",token);
        }else{
            //失败
            resultMap.put("code",401);
            resultMap.put("message","认证失败，请重新认证");
        }
        return resultMap;
    }
}